This project dives into the power of shaders to generate a dynamic, ocean-inspired scene entirely through code - no modeling required! Built using Three.js and GLSL, the waves are generated in real time using sine functions and time-based animation. The motion, form, and colors all respond to parameters controlled directly in the browser, revealing how code can sculpt and animate complex surfaces.
View Final ProductTech Stack
The foundation of the project started with a standard Three.js setup: creating a scene, configuring a perspective camera, and initializing a WebGL renderer. I also added responsive resizing and lighting to create a flexible environment suited for real-time animation. This foundation made it easy to focus on experimenting with shaders without worrying about structural or rendering issues down the line.
To simulate water realistically, I used a highly subdivided plane geometry as the base mesh. A dense grid of vertices was essential to create smooth and fluid movement using shader logic. Unlike static models, this geometry isn’t sculpted manually—instead, it acts as a canvas for real-time displacement handled entirely in the vertex shader.
The core visual behavior was built using custom GLSL shaders. In the vertex shader, I used a combination of sinus functions—modified by position and animated over time—to displace the surface and create lifelike wave motion. In the fragment shader, I introduced color gradients based on vertex elevation to simulate natural shading and depth.
To drive the movement, a uniform uTime variable was passed from the JavaScript animation loop into the shaders. This continuous stream of data allows the sine functions in the vertex shader to evolve frame-by-frame, creating an endlessly flowing, looping animation.
Together, these shaders bring the illusion of a realistic oceanic scene without any pre-made animations or models.
To make the project more interactive, I integrated lil-gui, a lightweight interface for real-time parameter control. This allows for modifiable shader parameters—such as wave frequency, amplitude, speed, and colors—to the browser. With this setup, the scene becomes an interactive playground where users (or I, during testing) can fine-tune the behavior and appearance of the scene instantly, without touching the code.
Note: This project was built using the fantastic lessons from Three.js Journey by Bruno Simon. Huge thanks to Bruno for teaching me the techniques and workflows that made this possible!
Coded with ♥ by Aurélie